/*
 * TinyXMLDocument.cpp
 *
 *  Created on: 2010-3-25
 *      Author: wenjian
 */

#include <vector>
#include "tinyxml/tinyxml.h"
#include "TinyXMLDocument.h"
#include "XMLDocument.h"
#include <iostream>

using namespace std;

namespace Try {

  TinyXMLDocument::TinyXMLDocument(){

  }

  TinyXMLDocument::~TinyXMLDocument() {

  }

  /**
   * 保存为文件
   */
  bool TinyXMLDocument::loadXML(const char* xml){
    TiXmlDocument tidoc;
    tidoc.Parse(xml);
    TiXmlElement* tiroot = tidoc.RootElement();
    if(!tiroot)return false; //载入失败
    XMLElement* root = newElement(tiroot->Value());
    setRootElement(root);
    parse(tiroot, root);
    return true;
  }

  /**
   * 载入XML文档
   */
  bool TinyXMLDocument::loadFile(const char* filename){
    TiXmlDocument tidoc;
    bool status = tidoc.LoadFile(filename);
    if(!status){
      return false;
    }
    TiXmlElement* tiroot = tidoc.RootElement();
    if(!tiroot){
      return false;
    }
    XMLElement* root = newElement(tiroot->Value());
    setRootElement(root);
    parse(tiroot, root);
    return true;
  }

  void TinyXMLDocument::parse(TiXmlElement* tinode, XMLElement* node){
    //设置节点文本值
    const char* text = tinode->GetText();
    if(text){
      node->setText(text);
    }
    //处理属性
    TiXmlAttribute* tiattr = tinode->FirstAttribute();
    while(tiattr){
      node->setAttribute(tiattr->Name(), tiattr->Value());
      tiattr = tiattr->Next();
    }
    //处理子节点
    TiXmlElement* tichild = tinode->FirstChildElement();
    while(tichild){
      XMLElement* child = newElement(tichild->Value());
      node->addChild(child);
      parse(tichild, child);
      tichild = tichild->NextSiblingElement();
    }
  }

  /**
   * 保存为文件
   */
  bool TinyXMLDocument::save(const char* filename, XMLDocument::Encoding encoding) {
    TiXmlDocument tidoc;
    completeTiXmlDocument(tidoc, encoding);
    return tidoc.SaveFile(filename);
  }

  /**
   * 保存为文件
   */
  const char* TinyXMLDocument::toXML(XMLDocument::Encoding encoding) {
    TiXmlDocument tidoc;
    completeTiXmlDocument(tidoc, encoding);
    TiXmlPrinter printer;
    tidoc.Accept( &printer );
    return printer.CStr();
  }

  void TinyXMLDocument::completeTiXmlDocument(TiXmlDocument& tidoc, XMLDocument::Encoding encoding){
    if(encoding==XMLDocument::UTF8){
      tidoc.LinkEndChild(new TiXmlDeclaration("1.0", "utf-8", ""));
      //tidoc.Parse("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
    }
    XMLElement* root = getRootElement();
    if(root){
      TiXmlElement* tiroot = new TiXmlElement(root->getName());
      tidoc.LinkEndChild(tiroot);
      buildTiXmlElement(tiroot, root);
    }
  }

  void TinyXMLDocument::buildTiXmlElement(TiXmlElement* tinode, XMLElement* node){
    //设置节点文本值
    const char* text = node->getText();
    if(text != NULL){
      tinode->LinkEndChild(new TiXmlText(text));
    }
    //处理属性
    const std::vector<XMLAttribute*>* attrs = node->getAttributes();
    if(attrs->size()>0){
      std::vector<XMLAttribute*>::const_iterator ait = attrs->begin();
      for(; ait!=attrs->end(); ait++){
        XMLAttribute* attr = *ait;
        tinode->SetAttribute(attr->getName(), attr->getValue());
      }
    }
    //处理子节点
    const std::vector<XMLElement*>* children = node->getChildren();
    if(children->size()>0){
      std::vector<XMLElement*>::const_iterator it = children->begin();
      for(; it!=children->end(); it++){
        TiXmlElement* tn = new TiXmlElement((*it)->getName());
        tinode->LinkEndChild(tn);
        buildTiXmlElement(tn, *it);
      }
    }
  }

}
